#include<iostream>
using namespace std;

template<typename T>
class SeqStack //模板名称+类型参数列表=类名称
{
public:
    //构造函数和析构函数名不用加<T>，其他出现模板的地方都要加上类型参数列表
    SeqStack(int size=10):_pstack(new T[size]),_top(0),_size(size){}
    ~SeqStack()
    {
        delete[] _pstack;
        _pstack = nullptr;
    }
    SeqStack(const SeqStack<T> &src):_top(src._top),_size(src._size)
    {
        _pstack = new T[_size];
        for (int i = 0; i < _top;i++)
        {
            _pstack[i] = src._pstack[i];
        }
    }
    SeqStack &operator=(const SeqStack<T> &src)
    {
        if(this==&src)
            return *this;
        delete[] _pstack;
        _top = src._top;
        _size = src._size;
        _pstack = new T[_size];
        for (int i = 0; i < _top; i++)
        {
            _pstack[i] = src._pstack[i];
        }
        return *this;
    }

    void push(const T &val)
    {
        if(full())
            expand();
        _pstack[_top++] = val;
    }
    void pop()
    {
        if(empty())
            return;
        _top--;
    }
    T top() const//只读方法使用常方法，普通对象和常对象都能调用
    {
        if(empty())
            throw "stack is empty!";
        return _pstack[_top-1];
    }
    bool full() const
    {
        return _top == _size;
    }
    bool empty() const
    {
        return _top == 0;
    }

private:
    T *_pstack;
    int _size;
    int _top;

    //顺序栈底层数组按照2倍的方式进行扩容
    void expand()
    {
        T *temp = new T[_size * 2];
        for (int i = 0; i < _top; i++)
        {
            temp[i] = _pstack[i];
        }
        delete[] _pstack;
        _pstack = temp;
        _size = _size * 2;
    }
};

int main()
{
    // 类模板的选择实例化，也就是说，这个SeqStack类里面包含了好很多种方法（函数模板方法）
    //要是不调用这些方法，这些方法将不会实例化，也就说不会进行编译，会减少编译器的工作
    SeqStack<int> s;
    s.push(10);
    s.push(20);
    cout << s.top() << endl;
    s.pop();

    return 0;
}